#include "http_request.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h> 
#include <ctype.h>

#define POSTMETHOD      "POST"
#define GETMETHOD       "GET"

/* http_request内存申请 */
static struct http_request *
http_request_malloc(void)
{
    struct http_request *request = NULL;
    if ((request = (struct http_request *)malloc(sizeof(struct http_request))) != NULL)
    {
        request->parameter = NULL;
    }
    return (request);
}

/* 将char转成对应的16进制：'1' -> 0x1, ‘A' -> 0xA */
static void
char_to_hex(int c, int *hex)
{
    if (isalpha(c))
    {
        *hex = toupper(c) - 'A' + 10;
    }
    else
    {
        *hex = c - '0';
    }
}

/* 将接收到的Unicode数据进行解析 */
static int
convert(char *inbuf, char *outbuf, size_t *outsize)
{
    if (inbuf == NULL || *inbuf == '\0' || outbuf == NULL)
    {
        return (-1);
    }
    while (*inbuf != '\0' && *outsize > 0)
    {
        int c;
        switch (*inbuf)
        {
        case '%':  /* Unicode */
            inbuf++;
            if (*inbuf == '\0' || *(inbuf + 1) == '\0')
            {
                return (-1);
            }
            int c1 = 0;
            int c2 = 0;
            char_to_hex(*inbuf++, &c1);
            char_to_hex(*inbuf, &c2);
            c = 0xFF & ((c1 << 4) | c2);
            break;

        case '+':
            c = ' ';
            break;
        
        default:
            c = *inbuf;
            break;
        }
        *outbuf++ = c;
        inbuf++;
        *outsize = *outsize - 1;;
    }
    *outbuf = '\0';
    return (0);
}

/* 设置键值对 */
static void
set_key_value(const char *parameter, const char *charset, struct key_value_pair *kv)
{
    char key[2048];
    char value[2048];
    memset(key, 0, sizeof(key));
    memset(value, 0, sizeof(value));

    sscanf(parameter, "%[^=]=%s", key, value);

    char outbuf[2048];
    size_t outsize;
    outsize = sizeof(outbuf);

    convert(key, outbuf, &outsize);
    kv->key = strdup(outbuf);

    outsize = sizeof(outbuf);
    memset(outbuf, 0, outsize);
    convert(value, outbuf, &outsize);
    kv->value = strdup(outbuf);
}

/* 将接收到的数据转成struct http_request类型 */
struct http_request *
string_to_http_requeset(char *request_data)
{
    if (request_data == NULL)
    {
        return (NULL);
    }

    /* 申请内存 */
    struct http_request *request = NULL;
    if (NULL == (request = http_request_malloc()))
    {
        return (NULL);
    }

    /* 处理header头 */
	sscanf(request_data, "%s %s %s\n", request->method, request->path, request->version);

    /* 只支持POST或GET请求 */
    if (strcmp(request->method, POSTMETHOD) != 0 && strcmp(request->method, GETMETHOD) != 0)
    {
        destroy_http_request(request);
        return (NULL); 
    }

    /* 获取Host */
    char *tmp = NULL;
    if ((tmp = strstr(request_data, "Host: ")) != NULL)
    {
        sscanf(tmp, "Host: %s\n", request->host);
    }

    /* 获取Conteng-Length*/
    if ((tmp = strstr(request_data, "Content-Length: ")) != NULL)
    {
        sscanf(tmp, "Content-Length: %d\n", &request->content_length);
    }

    /* 获取Content-Type以及charset */
    if ((tmp = strstr(request_data, "Content-Type: ")) != NULL)
    {
        sscanf(tmp, "Content-Type: %[^;]; charset=%s", request->content_type, request->charset);
    }

    if (strcmp(request->method, GETMETHOD) == 0)  /* GET */
    {
        if ((tmp = strstr(request->path, "?")) != NULL)
        {
            *tmp = '\0';
            tmp += strlen("?");
        }
    }
    else  /* POST */
    {
        if ((tmp = strstr(request_data, "\r\n\r\n")) != NULL)
        {
            tmp += strlen("\r\n\r\n");
        }
    }
    
    /* 处理请求数据 */
    if (tmp != NULL)
    {
        /* 生成参数单链表 */
        char *parameter = NULL;
        parameter = strtok(tmp, "&");
        struct key_value_pair *key_value_head = NULL;
        if (parameter != NULL && (key_value_head = key_value_pair_malloc()) != NULL)
        {
            set_key_value(parameter, request->charset, key_value_head);
            request->parameter = key_value_head;

            while ((parameter = strtok(NULL, "&")) != NULL)
            {
                struct key_value_pair *key_value = NULL;
                if ((key_value = key_value_pair_malloc()) != NULL)
                {
                    set_key_value(parameter, request->charset, key_value);
                    key_value_head->next = key_value;
                    key_value_head = key_value;
                }
            }
        }
    }  /* 结束处理请求数据 */

    return (request);
}

/* 释放http_request申请的内存 */
void
destroy_http_request(struct http_request *request)
{
    if (request != NULL)
    {
        destroy_key_value(request->parameter);
        free(request);
    }
}

/* 获取request中key对应的value, 并保存到大小为size的value中 */
int
get_parameter(struct http_request *request, const char *key, char *value, int size)
{
    if (request != NULL && request->parameter != NULL)
    {
        struct key_value_pair *key_value = NULL;
        key_value = request->parameter;

        while (key_value != NULL)
        {
           if (strcmp(key_value->key, key) == 0)
           {
               if (value == NULL)
               {
                   return (0);
               }

               snprintf(value, size, "%s", (char *)key_value->value);
               return (strlen(key_value->value));
           }
           key_value = key_value->next;
        }
    }
    return (-1);
}
